在本機做好 Docker image 後,接下來要把它推(push)上 AWS ECR repository~
開始前先註冊一個 AWS 帳號唷~還有在 AWS 裡要去各服務的頁面可以在左上角的搜尋框輸入關鍵字:
ECR 的全名是 Elastic Container Registry,是 AWS 提供來放 Docker image 的服務。我們可以在其中建立 public repository,像 Docker Hub 一樣公開存取,也能建立 private repository 在登入後才能存取 image。ECR 也跟 Elastic Container Service(ECS)和 Elastic Kubernetes Service(EKS)整合,ECS 跟 EKS 能簡單的存取 ECR 內的 image。
之後我們 ECS 便是從 ECR 取得網頁 application 的 image 來執行,所以現在要先知道如何把 image push 進 ECR repository。
要 push image 首先當然要有個存放 image 的 repository,讓我們進到 web console 來開一個吧~
點進 Repositories:
點 Create repository:
選擇 private repository 並輸入 repository name,後面設定保持預設點選 Create。
這樣就建立一個名叫 my-app
的 ECR repository 啦~接著要把 docker image push 進來。
因為我們使用 private repository,不像 public repository 可以直接使用,要經過 docker login
驗證才能存取 image。
AWS CLI 是 AWS 的 command line 工具,以指令操作各種 AWS 服務。AWS CLI 提供 get-login-password
命令讓我們可以用 docker login
對 ECR 做驗證。(ref)
我們先安裝 AWS CLI,參考 官方文件 即可順利安裝,Linux 的安裝指令如下:
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
$ aws --version # 確認是否安裝成功,成功會看到 aws cli 的版本
安裝 AWS CLI 後還要進行設定,它才知道並且能夠操作我們帳號內的各項服務與資源,設定方式參考 官方文件 用 aws configure
輸入 key id 跟 secret 等資訊。
咦?key id 跟 secret 要從哪來?讓我們進到 IAM(Identity and Access Management):
點 Users 下面的數字進入 Users 後找到要使用的 IAM user。如果你沒有建立 IAM user,可以參考 官方文件 建立一個 IAM user 來使用。一般建議不要以 AWS root account(就是直接用 email 登入的那個帳號)來操作,會新增一個擁有 AdministratorAccess
權限的 IAM user 進行平常的管理操作。進入該 IAM user 的畫面會看到下面有一排 tab:
到 Security credentials 的 tab,裡面會有一區 Access Keys:
只要你 access key 不到 2 把,就可以按右邊的 Create access key 來新增:
它會問你要拿 key 來做什麼、給你其他替代方案的建議,我們這邊先不深入這些選項,勾選底下的 I understand the above recommendation and want to proceed to create an access key 後 Next,下一頁可以選填描述,最後 Create key 會看到:
按 Secret access key 的 show 就會顯示 secret,這頁只會顯示一次,所以要配合 aws configure
一起設定好。
簡單介紹一下 IAM(Identity and Access Management),它是 AWS 控管權限的服務,裡面主要有 user、group、role 跟 policy。user 跟一般觀念的使用者一樣,可以登入跟操作。role 跟 user 有點像,簡單區分可以想成 user 是給「人」使用的「帳號」(實際上當然不是只給人用,程式也可以用 user 來打 API),role 則是給「AWS 的 service 或機器」使用的。policy 是權限的定義,定義什麼事可以做、什麼事不能做,一個 user、role 或 group 可以綁(attach)多個 policy、一個 policy 也可以 attach 到多個 user、role 或 group 上。group 如其名是群組,想讓某一群 user 有相同權限,可以建立一個 group 並 attach 相關 policy,再把這些 user 加進這個 group。
AWS 在權限方面採取「沒說可以做(allow)的事情就不能做(deny)」的原則,如果沒有明確在 policy 裡寫可以做某個操作(action),預設就是不能做該操作。實際使用上,我們應該讓 user 或 role 不多不少、剛好擁有需要的權限即可,像是只需要讀取 s3 上的檔案就只給 read-only 而不要給 full access,也不要給其他 service 的權限。
怎麼知道要給哪些權限呢?如果是常用情境,像是 push 跟 pull docker image,可以找找看 AWS 文件有沒有寫或者相關的 example。如果是自己寫的程式、沒有對應的 example 或文件,最簡單的方式就是把你要做的操作執行下去,AWS 通常會告訴你缺哪個 action,一個個補上直到能正常操作完畢。
要用 AWS CLI 跟 docker 登入 ECR,在 AWS 這部份需要以下的 IAM 權限 policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}
怎麼幫 IAM user 加 policy 呢?一樣進到那個 IAM user,在 Permissions 這個 tab 點右邊的 Add permissions,簡(ㄌㄢˇ)單(ㄉㄨㄛˋ) 一點可以直接 Create inline policy。
進到選擇要什麼 permission 的畫面後,因為我們已經有 json 了,右上角切換到 JSON 模式:
把上面的 policy json 貼進去後 Next:
幫 policy 取個名字後 Create policy,完成後便能在 Permissions 看到剛剛新增的 policy:
終於可以 docker login
了!
$ aws ecr get-login-password --region [region] | \
sudo docker login \
--username AWS \
--password-stdin [AWSAccountID].dkr.ecr.[region].amazonaws.com
上面的 [region]
跟 [AWSAccountID]
要換成你自己的,登入成功會看到 Login Succeed
。
總算可以推 image 了吧!不不不……還缺一個小小的步驟,那就是把 push image 到 ECR 需要的 IAM 權限 policy 加到 IAM user 身上 (ref):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:CompleteLayerUpload",
"ecr:GetAuthorizationToken",
"ecr:UploadLayerPart",
"ecr:InitiateLayerUpload",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage"
],
"Resource": "arn:aws:ecr:[REGION]:[ACCOUNT_ID]:repository/[REPO_NAME]"
}
]
}
這個 policy 是允許(allow)對 resource 指定的 ECR repository 做 action 裡的這些動作。(可以看到 action 分得非常細~)
終於要推 image 了!要推 image 進 ECR repository 要幫它上 tag 然後 push:
$ docker tag [ImageId] [AWSAccountID].dkr.ecr.[region].amazonaws.com/my-app:latest
$ docker push [AWSAccountID].dkr.ecr.[region].amazonaws.com/my-app:latest
push 成功的話,會在 ECR repository 看到像這樣的畫面:
docker tag 就像是幫 image 貼個好認的標籤,讓我們可以用標籤來指定某個 image,不然 image 是以 id 來識別的,應該不太有人能記住那些 id… 🧐
如果 image 只在本機使用,tag 想怎麼取都可以,但如果想要 push 出去(像我們要 push 到 ECR,或者想 push 到 Docker Hub),tag 必須遵照格式:[HOST[:PORT_NUMBER]/]PATH:[TAG]
,就像這裡的 [AWSAccountID].dkr.ecr.[region].amazonaws.com/my-app:latest
。host 與 port 是 registry 服務的 host name 跟 port,path 則是要 push 的 repository 所在位置,各家 registry 會有自己對 path 的定義。最後的 tag 可以不指定,預設會用 latest,通常會用來標示 image 的版本、使用的 base image OS 等等資訊。
既然有 push 也說明從 ECR repository pull image 需要的 IAM policy 以及指令,畢竟我們有可能需要 pull image 下來 debug 之類的。
pull image 需要的 IAM policy 如下:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
],
"Resource": "arn:aws:ecr:[REGION]:[ACCOUNT_ID]:repository/[REPOSITORY]"
}
]
}
把 policy 加到 IAM user 後就能 docker pull
ECR 上的 image:
$ docker pull [AWSAccountID].dkr.ecr.[region].amazonaws.com/my-app:latest